#include "DisplayDriver.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#ifdef __linux__
#include <unistd.h>
#endif


using namespace MC500;
using namespace std;

void DisplayDriver::WriteString(uint8_t x, uint8_t y, const string &str)
{
    for (uint32_t i = 0; i < str.length(); i++) {
        WriteChar(x, y, str[i]);
        x += 8;
    }
}

void DisplayDriver::WriteChar(uint8_t x, uint8_t y, char c)
{
    if (c >= '!' && c <= '~')
    {
        WriteImg(x, y, ASCIIChars[c - ' '], 8, 16);
    }
}

void DisplayDriver::print()
{
    for (int y = 0; y < LCD_Y_SIZE; y++)
    {
        uint8_t lineNO = y / 8;
        uint8_t byteOffset = (y % 8);
        uint8_t mask = 0x01 << byteOffset;
        for (int x = 0; x < LCD_X_SIZE; x++)
        {
            if ((lcdBuff_[lineNO][x] & mask) == 0)
            {
                cout << ".";
            }
            else
            {
                cout << "*";
            }
        }
        cout << endl;
    }
}

bool DisplayDriver::SendCMDToLCD(const uint8_t CMDID, const uint8_t Para)
{
    ostringstream buffer;
    buffer << static_cast<int>(CMDID) << static_cast<int>(Para) << "\r";
    std::string cmd = buffer.str();
    bus->Send((uint8_t *)cmd.c_str(), (uint16_t)cmd.length());
    uint8_t buff[50];
    uint16_t readLen = 0;
    bus->Read(buff, 50, readLen);
    buff[readLen] = '\0';
    if (readLen > 3 && strcmp((char *)buff, "I:A.") == 0)
    {
        return true;
    }
    else if (readLen > 3 && strcmp((char *)buff, "I:DATA.") == 0)
    {
        return true;
    }
    else
    {
        cout << "Send CMD " << static_cast<int>(CMDID) << " failed! ret=" << (char *)buff << endl;
        return false;
    }
}

bool DisplayDriver::SyncWithLCD()
{
    uint8_t sync[3] = {'\r','\n','\r'};
    bus->Send(sync, 3);
    uint8_t buff[50];
    uint16_t readLen = 0;
    bus->Read(buff, 50, readLen);
    buff[readLen] = '\0';
    if (readLen > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool DisplayDriver::SelectLine(const uint8_t line)
{
    return SendCMDToLCD(0, line);
}

bool DisplayDriver::SetX(const uint8_t x)
{
    return SendCMDToLCD(1, x);
}

bool DisplayDriver::SendDataToLCD(uint8_t *data, uint8_t len)
{
    if (!SendCMDToLCD(2, len))
    {
        cout << "Send data length failed!" << endl;
        return false;
    }

    bus->Send((uint8_t *)data, len);

    uint8_t sync[1] = {'\r'};
    bus->Send(sync, 1);

    uint8_t buff[50];
    uint16_t readLen = 0;
    bus->Read(buff, 50, readLen);
    buff[readLen] = '\0';
    if (readLen > 3 && strcmp((char *)buff, "I:Done.") == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void DisplayDriver::Refresh(bool lazy)
{
    if (!SyncWithLCD())
    {
        cout << "Sync with LCD failed!" << endl;
        return;
    }
    if (lazy)
    {
    }
    else
    {
        for (uint8_t line = 0; line < LCD_RENDER_Y_SZIE; line++)
        {
            if (!SelectLine(line))
            {
                cout << "Select line to " << static_cast<int>(line) << " failed!" << endl;
                continue;
            }
            if (!SetX(0))
            {
                cout << "Set X pos to 0 failed!" << endl;
                continue;
            }

            if (!SendDataToLCD(lcdBuff_[line], LCD_X_SIZE))
            {
                cout << "Send data failed!" << endl;
                continue;
            }
        }
    }
}



#define LowNBits2Top(byte, n) (byte << (8 - (n)))

#define HighNBits(byte, n)  ((byte >> (8 - (n))) << (8-(n)))

#define LowNBits(byte, n) ((byte << (8 - (n))) >> (8-(n)))

#define HighNBits2Button(byte, n) (byte >> (8 - (n)))

//写一行，由高镜像的 低highWriteBits位 和 低位镜像的高 8-highWriteBits位构成
void DisplayDriver::WriteLCDLineByCombine(const uint8_t x, const uint8_t lineNo, const uint8_t *highNImg, const uint8_t *lowImg, const uint8_t highWriteBits)
{

    //uint8_t highMask = (0xff >> (8 - highWriteBits)) << (8 - highWriteBits);

    uint8_t lowNBitsMask = (0xff >> (8 - highWriteBits));

    if (highNImg != nullptr)
    {
        lcdBuff_[lineNo][x] &= ~lowNBitsMask;
        lcdBuff_[lineNo][x] |= (lowNBitsMask) & HighNBits2Button(*highNImg, highWriteBits);
    }

    if (lowImg != nullptr)
    {
        lcdBuff_[lineNo][x] &= lowNBitsMask;
        lcdBuff_[lineNo][x] |= (~lowNBitsMask) & LowNBits2Top(*lowImg, 8 - highWriteBits);
    }
}

void DisplayDriver::WriteImg(const uint8_t x, const uint8_t y, const uint8_t *img, const uint8_t sizeX, const uint8_t sizeY)
{
    const uint8_t *writingBytes = img;
    //表明了本次写入LCD line 和 img Y轴字节对齐的偏移
    const uint8_t alignOffset = 8 - (y % 8);

    for (uint8_t currentYPos = y; currentYPos < y + sizeY;)
    {
        uint8_t currentlineNo = currentYPos / 8;
        //当前行buffer还有多宽可以写
        uint8_t bufferAbleWidth = (currentlineNo + 1) * 8 - currentYPos;

        for (uint8_t currentXPos = x; currentXPos < x + sizeX; currentXPos++)
        {
            if (alignOffset == 8)
            {
                if (currentYPos < LCD_Y_SIZE && currentXPos < LCD_X_SIZE)
                {
                    // 对齐写入。直接写
                    lcdBuff_[currentlineNo][currentXPos] = *writingBytes;
                }
                writingBytes++;
            }
            else
            {
                // 非对齐写入
                if (bufferAbleWidth < 8)
                {
                    if (currentYPos < LCD_Y_SIZE && currentXPos < LCD_X_SIZE)
                    {
                        // 写入底N位
                        WriteLCDLineByCombine(currentXPos, currentlineNo, nullptr, writingBytes, 8-alignOffset);
                    }
                    writingBytes++;
                }
                else if (currentYPos + 8 < y + sizeY)
                {
                    if (currentYPos < LCD_Y_SIZE && currentXPos < LCD_X_SIZE)
                    {
                        WriteLCDLineByCombine(currentXPos, currentlineNo, writingBytes - 8, writingBytes, 8-alignOffset);
                    }
                    writingBytes++;
                }
                else
                {
                    if (currentYPos < LCD_Y_SIZE && currentXPos < LCD_X_SIZE)
                    {
                        WriteLCDLineByCombine(currentXPos, currentlineNo, writingBytes - 8, nullptr, 8-alignOffset);
                    }
                    writingBytes++;
                }
            }
        }

        currentYPos += bufferAbleWidth;
    }
}

const uint8_t DisplayDriver::ASCIIChars[95][16] = {
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/
    {0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00}, /*"!",0*/
    {0x00, 0x10, 0x0C, 0x02, 0x10, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",1*/
    {0x00, 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x00, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x00}, /*"#",2*/
    {0x00, 0x70, 0x88, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0xFF, 0x21, 0x1E, 0x00}, /*"$",3*/
    {0xF0, 0x08, 0xF0, 0x80, 0x60, 0x18, 0x00, 0x00, 0x00, 0x31, 0x0C, 0x03, 0x1E, 0x21, 0x1E, 0x00}, /*"%",4*/
    {0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x2C, 0x19, 0x27, 0x21, 0x10}, /*"&",5*/
    {0x00, 0x12, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"'",6*/
    {0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00}, /*"(",7*/
    {0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00}, /*")",8*/
    {0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00}, /*"*",9*/
    {0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x01}, /*"+",10*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, /*",",11*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /*"-",12*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, /*".",13*/
    {0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x04, 0x00, 0x00, 0x60, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00}, /*"/",14*/
    {0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00}, /*"0",15*/
    {0x00, 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00}, /*"1",16*/
    {0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00}, /*"2",17*/
    {0x00, 0x30, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x18, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00}, /*"3",18*/
    {0x00, 0x00, 0x80, 0x40, 0x30, 0xF8, 0x00, 0x00, 0x00, 0x06, 0x05, 0x24, 0x24, 0x3F, 0x24, 0x24}, /*"4",19*/
    {0x00, 0xF8, 0x88, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00}, /*"5",20*/
    {0x00, 0xE0, 0x10, 0x88, 0x88, 0x90, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x20, 0x1F, 0x00}, /*"6",21*/
    {0x00, 0x18, 0x08, 0x08, 0x88, 0x68, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x00}, /*"7",22*/
    {0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00}, /*"8",23*/
    {0x00, 0xF0, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x01, 0x12, 0x22, 0x22, 0x11, 0x0F, 0x00}, /*"9",24*/
    {0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00}, /*":",25*/
    {0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00}, /*";",26*/
    {0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00}, /*"<",27*/
    {0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00}, /*"=",28*/
    {0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00}, /*">",29*/
    {0x00, 0x70, 0x48, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x30, 0x37, 0x00, 0x00, 0x00}, /*"?",30*/
    {0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x28, 0x2F, 0x28, 0x17, 0x00}, /*"@",31*/
    {0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20}, /*"A",32*/
    {0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00}, /*"B",33*/
    {0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00}, /*"C",34*/
    {0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00}, /*"D",35*/
    {0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00}, /*"E",36*/
    {0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00}, /*"F",37*/
    {0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00}, /*"G",38*/
    {0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20}, /*"H",39*/
    {0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, /*"I",40*/
    {0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00}, /*"J",41*/
    {0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00}, /*"K",42*/
    {0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00}, /*"L",43*/
    {0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x01, 0x3E, 0x01, 0x3F, 0x20, 0x00}, /*"M",44*/
    {0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00}, /*"N",45*/
    {0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00}, /*"O",46*/
    {0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00}, /*"P",47*/
    {0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x28, 0x28, 0x30, 0x50, 0x4F, 0x00}, /*"Q",48*/
    {0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20}, /*"R",49*/
    {0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00}, /*"S",50*/
    {0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00}, /*"T",51*/
    {0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00}, /*"U",52*/
    {0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00}, /*"V",53*/
    {0x08, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x00, 0x03, 0x3E, 0x01, 0x3E, 0x03, 0x00, 0x00}, /*"W",54*/
    {0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20}, /*"X",55*/
    {0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00}, /*"Y",56*/
    {0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00}, /*"Z",57*/
    {0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00}, /*"[",58*/
    {0x00, 0x04, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00}, /*"\",59*/
    {0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00}, /*"]",60*/
    {0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"^",61*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, /*"_",62*/
    {0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"`",63*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x19, 0x24, 0x24, 0x12, 0x3F, 0x20, 0x00}, /*"a",64*/
    {0x10, 0xF0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00}, /*"b",65*/
    {0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00}, /*"c",66*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x90, 0xF0, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20}, /*"d",67*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x24, 0x24, 0x24, 0x24, 0x17, 0x00}, /*"e",68*/
    {0x00, 0x80, 0x80, 0xE0, 0x90, 0x90, 0x20, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, /*"f",69*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00}, /*"g",70*/
    {0x10, 0xF0, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20}, /*"h",71*/
    {0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, /*"i",72*/
    {0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00}, /*"j",73*/
    {0x10, 0xF0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x06, 0x29, 0x30, 0x20, 0x00}, /*"k",74*/
    {0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00}, /*"l",75*/
    {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F}, /*"m",76*/
    {0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20}, /*"n",77*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00}, /*"o",78*/
    {0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x91, 0x20, 0x20, 0x11, 0x0E, 0x00}, /*"p",79*/
    {0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x91, 0xFF, 0x80}, /*"q",80*/
    {0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00}, /*"r",81*/
    {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00}, /*"s",82*/
    {0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x10, 0x00}, /*"t",83*/
    {0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20}, /*"u",84*/
    {0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x03, 0x0C, 0x30, 0x0C, 0x03, 0x00, 0x00}, /*"v",85*/
    {0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x01, 0x0E, 0x30, 0x0C, 0x07, 0x38, 0x06, 0x01}, /*"w",86*/
    {0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x0E, 0x2E, 0x31, 0x20, 0x00}, /*"x",87*/
    {0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x81, 0x86, 0x78, 0x18, 0x06, 0x01, 0x00}, /*"y",88*/
    {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00}, /*"z",89*/
    {0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3E, 0x40, 0x40}, /*"{",90*/
    {0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, /*"|",91*/
    {0x02, 0x02, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00}, /*"}",92*/
    {0x00, 0x02, 0x01, 0x02, 0x02, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"~",93*/
};